#include "rtsp_client.h"

#include "myregex.h"
#include "rtp.h"
#include "utils.h"

#include <fstream>
#include <iostream>
#include <regex>
#include <sstream>
#include <string.h>
#include <vector>

ErrorType RtspClient::PlayUri(std::string uri) {
    int         port;
    std::string ipstr;
    bool        b_ret = GetMsgFromUri(uri, ipstr, port, username_, password_);
    std::cout << ipstr << std::endl;
    uri_ = uri;
    //    username_         = "admin";
    //    password_         = "hy123456";
    std::cout << uri_ << std::endl;
    std::cout << "username:" << username_ << ",password:" << password_ << std::endl;
    std::cout << "----------------------------" << std::endl;

    bool bret = client_.Connect(ipstr.c_str(), port);
    if (bret) {
        ErrorType etype = DoOPTIONS(uri);
        if (etype == RTSP_NO_ERROR) {
            /* code */
        }
        etype = DoDESCRIBE(uri);
        assert(etype == RTSP_NO_ERROR);
        etype = DoSETUP();
        assert(etype == RTSP_NO_ERROR);
        etype = DoPLAY();
        assert(etype == RTSP_NO_ERROR);
    }

    return RTSP_NO_ERROR;
}

ErrorType RtspClient::Stop() {
    printf("stop rtsp client.\n");
    b_thread_switch_ = false;
    if (recv_vdieo_data_th_.joinable()) {
        recv_vdieo_data_th_.join();
    }
    if (keeplive_thd_.joinable()) {
        keeplive_thd_.join();
    }
    return RTSP_NO_ERROR;
}

bool RtspClient::CheckDESMsgcompleted(const char* msg, int& wantlen) {
    std::vector<std::string> result;
    result = split(msg, "\r\n");
    printf("result-size:%d\n", result.size());
    for (size_t i = 0; i < result.size(); i++) {
        int ipos = result[i].find("Content-Length:");
        if (ipos != std::string::npos) {
            std::string contentlen =
              result[i].substr(ipos + sizeof("Content-Length:"), result[i].size() - 1 - ipos);
            // printf("contentlen:%s\n", contentlen.c_str());
            wantlen = atoi(contentlen.c_str()) - strlen(msg);
            printf("wantlen:%d\n", wantlen);
            if (wantlen == 0) {
                return true;
            }

            return false;
        }
    }
    return false;
}

bool RtspClient::CheckDESMediaMsg(const std::string msg) {
    if (msg.find("m=video") != std::string::npos) {
        return true;
    }
    return false;
}

ErrorType RtspClient::DoDESCRIBE(std::string uri) {
    std::string msg  = GetRtspProtoMsg("DESCRIBE");
    bool        bret = client_.Send(msg.c_str(), msg.length());
    if (bret) {
        char recvmsg[100 * 1024]{0};
        int  len{sizeof(recvmsg)};
        client_.GetRecv(recvmsg, len);
        // int wantlen = 0;
        // CheckDESMsgcompleted(recvmsg, wantlen);
        //检查是否拿到SDP信息
        bool bhas = CheckDESMediaMsg(recvmsg);
        if (bhas == false) {
            int tlen = sizeof(recvmsg) - len;
            client_.GetRecv(recvmsg + len, tlen);
        }
        printf("line:%d msg:\n%s\n", __LINE__, recvmsg);
        ResponseMsg res_msg = GetResponseMsg(recvmsg);
        if (res_msg.no == 200) {
            printf("200 OK\n");
        } else if (res_msg.no == 401) {
            printf("401 Unauthorized\n");
            CheckAuth("DESCRIBE", recvmsg);
            client_.GetRecv(recvmsg, len);
            printf("au-msg:\n%s\n", recvmsg);
        }
        // FILE* fp = fopen("../test/rtspmsg/sdp_tmp.txt", "w"); /* 得到含有rtsp消息的文件 */
        // fwrite(recvmsg, strlen(recvmsg) + 1, 1, fp);
        // fclose(fp);
        AnalySDPMessage(uri_, recvmsg);
    }

    return RTSP_NO_ERROR;
}

ErrorType RtspClient::DoOPTIONS(std::string uri) {
    std::string msg  = GetRtspProtoMsg("OPTIONS");
    bool        bret = client_.Send(msg.c_str(), msg.length());
    if (bret) {
        char recvmsg[10 * 1024]{0};
        int  len{sizeof(recvmsg)};
        int  rlen = client_.GetRecv(recvmsg, len);
        if (rlen) {
            printf("msg:%s\n", recvmsg);
            ResponseMsg res_msg = GetResponseMsg(recvmsg);
            if (res_msg.no == 200) {
                printf("200 OK\n");
            } else if (res_msg.no == 401) {
                printf("401 Unauthorized\n");
                CheckAuth("OPTIONS", recvmsg);
                client_.GetRecv(recvmsg, len);
                printf("au-msg:\n%s\n", recvmsg);
            } else {
                printf("DoOPTIONS-errno:%d errstr:%s\n", res_msg.no, res_msg.msg.c_str());
                return RTSP_UNKNOWN_ERROR;
            }
        }
    } else {
        return RTSP_SEND_ERROR;
    }

    return RTSP_NO_ERROR;
}

ErrorType RtspClient::DoSETUP() {
    printf("DoSETUP-m_uri_:%s\n", m_uri_.c_str());
    // setup 视频流

    std::string cmd(GetRtspProtoMsg("SETUP"));
    std::cout << "Send-SETUP:" << std::endl;
    std::cout << cmd << std::endl;
    bool bret = client_.Send(cmd.c_str(), cmd.length());
    if (bret) {
        char recvmsg[10 * 1024]{0};
        int  len{sizeof(recvmsg)};
        client_.GetRecv(recvmsg, len);
        printf("setup msg:\n%s\n", recvmsg);
        ResponseMsg res_msg = GetResponseMsg(recvmsg);
        if (res_msg.no == 200) {
            GetSessionID(recvmsg);
        } else if (res_msg.no == 401) {
            return RTSP_RESPONSE_401;
        } else {
            return RTSP_UNKNOWN_ERROR;
        }
    }
    return RTSP_NO_ERROR;
}

ErrorType RtspClient::DoPLAY() {
    std::string cmd(GetRtspProtoMsg("PLAY"));
    std::cout << "DoPLAY" << std::endl;
    std::cout << cmd << std::endl;
    bool bret = client_.Send(cmd.c_str(), cmd.length());
    std::cout << "Send PLAY MSG-bret:" << std::boolalpha << bret << std::endl;
    if (bret) {
        char recvmsg[RECV_BUF_SIZE]{0};
        int  len{sizeof(recvmsg)};
        int  retlen = client_.GetRecv(recvmsg, len);
        printf("play recv-retlen:%d\n", retlen);
        printf("play recv msg:%s\n", recvmsg);
        // usleep(10 * 1000);
        // AnalySDPMessage(recvmsg, SETUP);
        StartRecvVideoData();
    }
    return RTSP_NO_ERROR;
}

ErrorType RtspClient::DOTEARDOWN() {
    close_flag       = true;
    b_thread_switch_ = false;

    std::string cmd(GetRtspProtoMsg("TEARDOWN"));
    std::cout << "TEARDOWN" << std::endl;
    std::cout << cmd << std::endl;
    bool bret = client_.Send(cmd.c_str(), cmd.length());

    // SendRTCPBye(ssrc);

    // if (bret) {
    //     char recvmsg[RECV_BUF_SIZE]{0};
    //     int  len{sizeof(recvmsg)};
    //     int  retlen = client_.GetRecv(recvmsg, len);
    //     printf("teardown recv-retlen:%d\n", retlen);
    //     printf("teardown recv msg:%s\n", recvmsg);

    // }

    return RTSP_NO_ERROR;
}

void RtspClient::SendRTCPBye(std::string ssrc_) {
    //发送RTCP—BYE
    InterFrameHeader ifheader;
    RtcpMsg          rtcp_msg_;

    ifheader.ch_num = 1;
    // std::cout << "BYE--ssrc: " << ssrc << std::endl;
    std::string byestr = rtcp_msg_.GetBYEMsg(ssrc_);
    std::string rrstr  = rtcp_msg_.GetRRMsg();

    ifheader.data_len = rrstr.length() + byestr.length();
    ifheader.data_len = htons(ifheader.data_len);

    std::string str;
    str.resize(sizeof(InterFrameHeader) + ntohs(ifheader.data_len));

    memcpy(&str[0], (char*)&ifheader, sizeof(InterFrameHeader));
    memcpy(&str[sizeof(InterFrameHeader)], rrstr.c_str(), rrstr.length());
    memcpy(&str[sizeof(InterFrameHeader) + rrstr.length()], byestr.c_str(), byestr.length());
    bool b_ret = client_.Send(str.c_str(), str.length());
}

std::string RtspClient::GetRtspProtoMsg(std::string cmd) {
    std::stringstream msg("");
    if (cmd == "OPTIONS") {
        // std::stringstream msg("");
        msg << cmd << " " << uri_ << " "
            << "RTSP/" << VERSION_RTSP << "\r\n";
        msg << "CSeq: " << ++cseq_ << "\r\n";
        msg << "User-Agent: ivs/1.0 (Streaming Media " + std::string(RTSPMODULEVERSION) + ")\r\n";
        msg << "\r\n";
    } else if (cmd == "DESCRIBE") {
        // std::stringstream msg("");
        msg << cmd << " " << uri_ << " "
            << "RTSP/" << VERSION_RTSP << "\r\n";
        msg << "CSeq: " << ++cseq_ << "\r\n";
        msg << "User-Agent: ivs/1.0 (Streaming Media " + std::string(RTSPMODULEVERSION) + ")\r\n";
        msg << "\r\n";
    } else if (cmd == "SETUP") {
        msg << cmd << " " << m_uri_ << " "
            << "RTSP/" << VERSION_RTSP << "\r\n";
        msg << "CSeq: " << ++cseq_ << "\r\n";
        msg << "Transport:"
            << " "
            << "RTP/AVP"
            << "/TCP;";
        msg << "unicast;interleaved=0-1\r\n";
        msg << "\r\n";
    } else if (cmd == "PLAY") {
        // std::stringstream msg("");
        msg << cmd << " " << uri_ << " "
            << "RTSP/" << VERSION_RTSP << "\r\n";
        msg << "CSeq: " << ++cseq_ << "\r\n";
        msg << "User-Agent: ivs/1.0 (Streaming Media " + std::string(RTSPMODULEVERSION) + ")\r\n";
        msg << "Session: " << session_ << "\r\n";
        msg << "Range: npt=0.000-\r\n";
        msg << "\r\n";
    } else if (cmd == "TEARDOWN") {
        std::string md5response;
        md5response = MakeMd5DigestResp(cmd, realm, nonce);
        // printf("Md5Response:%s\n", md5response.c_str());
        if (md5response.length() != MD5_SIZE) {
            std::cout << "Make MD5 digest response error" << std::endl;
        }

        msg << cmd << " " << uri_ << " "
            << "RTSP/" << VERSION_RTSP << "\r\n";
        msg << "CSeq: " << ++cseq_ << "\r\n";
        msg << "Authorization: Digest username=\"" << username_ << "\", realm=\"" << realm
            << "\", nonce=\"" << nonce << "\", uri=\"" << uri_ << "\", response=\"" << md5response
            << "\"\r\n";
        msg << "User-Agent: ivs/1.0 (Streaming Media " + std::string(RTSPMODULEVERSION) + ")\r\n";
        msg << "Session:" << session_ << "\r\n";
        msg << "\r\n";
    }

    return msg.str();
}

ResponseMsg RtspClient::GetResponseMsg(std::string msg) {
    ResponseMsg              res_msg;
    std::vector<std::string> vstr = split(msg, "\r\n");
    for (size_t i = 0; i < vstr.size(); i++) {
        if (strncmp(vstr[i].c_str(), "RTSP/", 4) == 0) {  // vstr[i].compare(0,4,"RTSP/"
            printf("###-%s\n", vstr[i].c_str());
            std::vector<std::string> vstrno = split(msg, " ");
            if (vstrno.size() > 3) {
                res_msg.no  = atoi(vstrno[1].c_str());
                res_msg.msg = vstrno[2];
                printf("str_rtsp_no:%d str_rtsp_msg:%s\n", res_msg.no, res_msg.msg.c_str());
            }
        }
    }
    return res_msg;
}

void RtspClient::StartRecvVideoData() {
    recv_vdieo_data_th_ = std::thread([this]() { RecvVideoDataFunc(); });
    keeplive_thd_       = std::thread([this]() {
        while (b_thread_switch_) {
            //发送rtcp数据保活
            if (client_.GetHeartBeatStatus()) {
                //这里的RR包只充当心跳包功能
                std::string str  = rtpdepay_.GetRTCPRRMsg();
                bool        bret = client_.Send(str.c_str(), str.length());
                std::cout << "keep live -send rtcp rr." << std::endl;
            }
            std::this_thread::sleep_for(std::chrono::seconds(5));
        }
    });
}

void RtspClient::RecvVideoDataFunc() {
    rtpdepay_.SetRTCPFunc([this](std::string rtcp_msg) {
        bool b_ret = client_.Send(rtcp_msg.c_str(), rtcp_msg.length());
        printf("b_ret:%d length:%d\n", b_ret, rtcp_msg.length());
    });
    rtpdepay_.SetDepayFunc([this](PayloadType pt, std::vector<u_char>& one_rtp_pack) {
        parse_.PushRtpPack(pt, one_rtp_pack);
    });
    parse_.SetParseFunc([this](PayloadType pt, uint32_t time_stamp, u_int32_t nalutype,
                               std::vector<u_char>& one_rtp_pack) {
        // parse_.PushRtpPack(pt, one_rtp_pack);
        // std::ofstream ofs("out.264", std::ios::app | std::ios::binary);
        // ofs.write((const char*)&one_rtp_pack[0], one_rtp_pack.size());
        if (stream_func_) {
            stream_func_(pt, time_stamp, nalutype, one_rtp_pack);
        }
    });
    while (b_thread_switch_) {
        char recvmsg[RECV_BUF_SIZE]{0};
        int  len{sizeof(recvmsg)};
        int  rlen      = client_.GetRecv(recvmsg, len);
        auto beginTime = std::chrono::high_resolution_clock::now();
        // {
        //     std::ofstream ofs("out_217.264", std::ios::app | std::ios::binary);
        //     ofs.write((const char*)recvmsg, len);
        // }
        bool bret = rtpdepay_.PushRtpData(H264, (u_char*)recvmsg, rlen, close_flag);
        if (bret) {
            auto endTime = std::chrono::high_resolution_clock::now();
            auto elapsedTime =
              std::chrono::duration_cast<std::chrono::milliseconds>(endTime - beginTime);
        }
        // std::cout << "GetRecv time is " << elapsedTime.count() << " milliseconds" << std::endl;

        // printf("RecvVideoDataFunc-len:%d\n", rlen);
    }
}

ErrorType RtspClient::CheckAuth(std::string cmd, std::string response) {
    MyRegex                regex;
    std::list<std::string> group;
    std::string            pattern_digest(
                 "WWW-Authenticate: *Digest +realm=\"([a-zA-Z_0-9 ]+)\", *nonce=\"([a-zA-Z0-9]+)\"");
    std::string       pattern_basic("WWW-Authenticate: *Basic +realm=\"([a-zA-Z_0-9 ]+)\"");
    std::string       realmtmp("");
    std::stringstream msg("");
    // std::string       rtspUri = RtspURI;

    msg << cmd << " " << uri_ << " "
        << "RTSP/" << VERSION_RTSP << "\r\n";
    msg << "CSeq: " << ++cseq_ << "\r\n";

    if (regex.Regex(response.c_str(), pattern_digest.c_str(), &group)) {
        std::string md5response;
        std::string noncetmp;
        // cout << "Regex hit" << endl;
        group.pop_front();
        realmtmp = group.front();
        group.pop_front();
        noncetmp    = group.front();
        realm       = realmtmp;
        nonce       = noncetmp;
        md5response = MakeMd5DigestResp(cmd, realm, nonce);
        printf("Md5Response:%s\n", md5response.c_str());
        if (md5response.length() != MD5_SIZE) {
            std::cout << "Make MD5 digest response error" << std::endl;
            return RTSP_UNKNOWN_ERROR;
        }
        msg << "Authorization: Digest username=\"" << username_ << "\", realm=\"" << realmtmp
            << "\", nonce=\"" << noncetmp << "\", uri=\"" << uri_ << "\", response=\""
            << md5response << "\"\r\n";
        printf("msg:\n%s\n", msg.str().c_str());
    } else if (regex.Regex(response.c_str(), pattern_basic.c_str(), &group)) {
        string BasicResponse("");
        group.pop_front();
        realmtmp.assign(group.front());
        realm.assign(realmtmp);
        BasicResponse = MakeBasicResp();
        msg << "Authorization: Basic " << BasicResponse;
    }
    msg << "\r\n";
    printf("au-snd:\n%s\n", msg.str().c_str());
    client_.Send(msg.str().c_str(), msg.str().length());

    return RTSP_NO_ERROR;
}

void RtspClient::AnalySDPMessage(std::string uri, std::string msg) {
    using namespace std;

    int                      iPos;
    string                   tmp;
    string                   message = msg;
    string                   head{0x00, 0x00, 0x00, 0x01};
    std::vector<std::string> result;

    cout << "----------------AnalySDPMessage------------------" << endl;
    if ((iPos = message.find("H264")) != string::npos) /* jduge video */
        cout << "video:H264" << endl;
    else
        cout << "video is not H264" << endl;

    if ((iPos = message.find("x-dimensions:")) != string::npos) {
        tmp     = message.substr(iPos + 13);
        result  = split(tmp, "\r\n");
        result  = split(result[0], ",");
        iHeight = atoi(result[0].c_str());
        iWidth  = atoi(result[1].c_str());
        printf("ImageResolution: %d X %d \n", iHeight, iWidth);
    } else {
        iHeight = 0;
        iWidth  = 0;
        printf("msg not has x-dimensions, analy failed!\n");
    }

    if ((iPos = message.find("m=video")) != string::npos) {
        tmp = message.substr(iPos);
        printf("tmp:\n%s\n", tmp.c_str());

        if ((iPos = tmp.find("a=control:")) != string::npos) {
            tmp = tmp.substr(iPos);
            printf("tmp:\n%s\n", tmp.c_str());
            result = split(tmp, "\r\n");
            m_uri_ = result[0].substr(strlen("a=control:"));
            if (m_uri_.find("rtsp") != 0) {
                cout << "1-uri_:" << uri << endl;
                m_uri_ = uri + "/" + m_uri_;
            }
            cout << "1-m_uri_:" << m_uri_ << endl;
        }
    }

    if ((iPos = message.find("sprop-parameter-sets=")) != string::npos) {
        tmp    = message.substr(iPos + 21);
        result = split(tmp, "\r\n");
        result = split(result[0], ",");

        spsDecode = b64decodestring(result[0]); /* result[0]:spsEncode */
        ppsDecode = b64decodestring(result[1]); /* result[1]:ppsEncode */

        spsDecode.insert(0, head);
        ppsDecode.insert(0, head);
        spsDecode.append(ppsDecode);
        // FILE* fp = fopen("./test.h264", "w"); /* 得到含有pps和ssp的文件 */
        // fwrite(spsDecode.c_str(), spsDecode.length() + 1, 1, fp);
        // fclose(fp);
    }

    if ((iPos = message.find("rtpmap:96")) != string::npos) {
        // a=rtpmap:96 H264/90000,len+1(跳过空格)
        tmp = message.substr(iPos + 10);

        result = split(tmp, "\r\n");
        result = split(result[0], "/");

        vCodeFormat   = result[0];
        iSamplingRate = atoi(result[1].c_str());
    }
    cout << "------------------------------------------------" << endl;
}

void RtspClient::GetSessionID(std::string msg) {
    int                      iPos;
    string                   tmp;
    std::vector<std::string> result;

    printf("-----------------GetSessionID------------------------\n");
    std::cout << msg << std::endl;

    if ((iPos = msg.find("Session:")) != string::npos) {
        tmp       = msg.substr(iPos);
        result    = split(tmp, "\r\n");
        result[0] = result[0].substr(9);
        result    = split(result[0], ";");
        while (1) {
            if ((iPos = result[0].find(" ")) != string::npos) {
                result[0] = result[0].substr((iPos + 1));
            } else {
                break;
            }
        }
        session_ = result[0];
        std::cout << "session_:" << session_ << std::endl;
    }
    if ((iPos = msg.find("interleaved=")) != string::npos) {
        tmp         = msg.substr(iPos);
        result      = split(tmp, "\r\n");
        result[0]   = result[0].substr(12);
        result      = split(result[0], ";");
        interleaved = result[0];
        std::cout << "interleaved=:" << interleaved << std::endl;
    }

    if ((iPos = msg.find("ssrc=")) != string::npos) {
        tmp       = msg.substr(iPos);
        result    = split(tmp, "\r\n");
        result[0] = result[0].substr(5);
        result    = split(result[0], ";");
        ssrc      = result[0];
        std::cout << "ssrc:" << ssrc << std::endl;
    }
    std::cout << "-------------------------------------------------" << std::endl;
}

std::string RtspClient::MakeMd5DigestResp(std::string cmd, std::string realm, std::string nonce) {
    std::string tmp("");

    char ha1buf[MD5_SIZE + 1] = {0};
    char ha2buf[MD5_SIZE + 1] = {0};
    char habuf[MD5_SIZE + 1]  = {0};

    if (username_.length() <= 0 || password_.length() <= 0) {
        return "";
    }

    tmp = username_ + ":" + realm + ":" + password_;
    printf("1-tmp:%s\n", tmp.c_str());
    Md5sum32((void*)tmp.c_str(), (unsigned char*)ha1buf, tmp.length(), MD5_SIZE);
    ha1buf[MD5_SIZE] = '\0';

    tmp.assign("");
    tmp = cmd + ":" + uri_;
    printf("2-tmp:%s\n", tmp.c_str());
    Md5sum32((void*)tmp.c_str(), (unsigned char*)ha2buf, tmp.length(), MD5_SIZE);
    ha2buf[MD5_SIZE] = '\0';

    tmp = ha1buf;
    tmp = tmp + ":" + nonce + ":" + ha2buf;
    printf("3-tmp:%s\n", tmp.c_str());
    Md5sum32((void*)tmp.c_str(), (unsigned char*)habuf, tmp.length(), MD5_BUF_SIZE);
    habuf[MD5_SIZE] = '\0';

    tmp = habuf;

    return tmp;
}

string RtspClient::MakeBasicResp() {
    string tmp          = username_ + ":" + password_;
    char*  encodedBytes = base64Encode(tmp.c_str(), tmp.length());
    if (NULL == encodedBytes) {
        return "";
    }
    tmp.assign(encodedBytes);
    delete[] encodedBytes;

    return tmp;
}

bool RtspClient::GetMsgFromUri(std::string uri, std::string& ipstr, int& port, std::string& user,
                               std::string& password) {
    using namespace std;
    smatch results;
    // m_rtspclient.PlayUri("rtsp://admin:gyz123456@192.168.28.29:554/");
    string patternIp(
      "((25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)"
      "))");
    string patternPort("\\.\\d{0,3}:\\d{0,5}");

    string patternUserAndPass("//.*@");

    string pattern1(
      "^rtsp://(\\w{1,20}:\\w{1,20}@)?\
((25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\
(:([0-9]|[1-9]\\d{1,3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5]))?/?(.*$)?");

    string getPort;
    string ip;
    int    pos;
    regex  r(pattern1);
    regex  r1(patternIp);
    regex  r2(patternPort);
    regex  r3(patternUserAndPass);

    if (regex_match(uri, results, r)) /* 完全匹配uir */
    {
        cout << results[0] << endl;
    } else {
        cout << "wrong format" << endl;
        return false;
    }

    if (regex_search(uri, results, r1)) /* get port */
    {
        cout << results[0] << endl;
    }
    ip = results[0].str();

    if (!regex_search(uri, results, r2)) /* get ip */
    {
        cout << "not find port" << endl;
        port = 554;
    } else {
        getPort = results[0].str();
        getPort = getPort.substr(getPort.find(':') + 1);
        port    = atoi(getPort.c_str());
    }
    cout << port << endl;

    if (regex_search(uri, results, r3)) /* 匹配只有用户名和密码 */
    {
        //		cout<<results[0]<<endl;
        user = results[0].str();

        password = user.substr(user.find(':') + 1);
        cout << password << endl;
        pos      = password.find_first_of("@");
        password = password.substr(0, pos); /* get password */

        cout << user << endl;
        pos  = user.find_first_of(":");
        user = user.substr(2, pos - 2); /* get user */

        pos = uri.find('/') + 2;
        uri.erase(pos, results[0].length() - 2); /* 去掉用户名和密码的uri */
    } else {
        cout << "not find" << endl;
    }

    ipstr = ip;

    return true;
}